<template>
  <div flex-1 h-full overflow-x-hidden>
    <a-spin :spinning="loading > 0">
      <div
        px-8
        w-full
        h-screen
        overflow-y-auto
        py-4
        flex
        flex-col
        id="selection_container"
      >
        <Step
          my-30px
          v-model="currentStep"
          :change="changeStep"
          :stepInfo="stepInfo"
        />
        <div pl-4 text-xl font-bold>待对齐类目</div>
        <Nav
          :category-code="categoryCode"
          :category-name="categoryName"
          :category-nav="categoryPath"
          my-30px
        />
        <component
          v-if="currentProcess.process"
          :is="Comp[currentProcess.process]"
          :stepData="currentProcess"
          :fetchProcess="fetchProcess"
          :updateProcess="updateProcess"
          @jump="jump"
          ref="instanceRef"
        ></component>
      </div>
    </a-spin>
    <a-modal v-model:open="open">
      <template #title>
        <div flex items-center>
          <ExclamationCircleOutlined class="text-warning mr-3 text-22px" />
          提示
        </div>
      </template>
      <div my-20px>未保存的操作将会丢失，是否需要保存？</div>
      <template #footer>
        <a-space>
          <a-button type="primary" danger @click="onOk">是</a-button>
          <a-button danger @click="onCancel">否</a-button>
          <a-button danger @click="open = false">取消</a-button>
        </a-space>
      </template>
    </a-modal>
  </div>
</template>

<script setup lang="tsx">
import Nav from './Nav.vue';
import Step from './Step.vue';
import Start from './Start/index.vue';
import Match from './Match/index.vue';
import Option from './Option/index.vue';
import Result from './Result/index.vue';
import { process_get, process_update } from '@/api/process';
import { JobStep, ProcessType, processCollections } from './Step';
import type { Category } from '@/types/category';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { JumpType, UpdateProcess } from './type';
import event from './event';

const Comp: Partial<Record<ProcessType, Component>> = {
  START: Start,
  CONDITION_RELATION: Match,
  OPTION_RELATION: Option,
  RESULT_ADJUST: Result,
};
const currentStep = computed(() =>
  processCollections.findIndex(item => item == currentProcess.value.process),
);
const loading = ref(0);

const {
  categoryCode,
  categoryName,
  categoryPath,
  id: categoryId,
} = st.get('_category') as Category;

const hasProcess = ref(false);

const stepInfo = ref(new JobStep());
const currentProcess = ref(new JobStep());

onMounted(() => {
  fetchProcess('START');
});

const fetchProcess = async (processName: ProcessType) => {
  loading.value++;
  const res = await process_get(categoryId);
  if (res.code == 'ok') {
    if (res.data.length) {
      hasProcess.value = true;
      const jobs = parseJson(res.data[0].data, []);
      let dummy = new JobStep();
      for (let item of jobs) {
        if (item.process == 'START') {
          item.data.type = 'MERGER';
        }
        dummy.addNext(new JobStep(item.process, item.data));
      }
      stepInfo.value = dummy.next!;
    } else {
      stepInfo.value = new JobStep('START', {
        mapping_categories: [],
        hancode_category: st.get('_category') as Category,
      });
    }
    let step = stepInfo.value.getStep(processName);
    if (!step) {
      step = new JobStep(processName, {});
      stepInfo.value.addNext(step);
    }
    currentProcess.value = step;
    loading.value--;
  }
};

const updateProcess: UpdateProcess = async (confirmed = false) => {
  loading.value++;
  let res = await process_update({
    cid: categoryId,
    data: stepInfo.value.format(),
    jobStep: currentProcess.value.process!,
    confirmed,
  });
  loading.value--;
  return res;
};

const open = ref(false);
const jumpProcess = ref('' as ProcessType);
const jumpCallback = ref();
const jump = ({ process_name, callback, isNext }: JumpType) => {
  jumpProcess.value = process_name;
  jumpCallback.value = callback;
  if (isNext) {
    return onOk();
  }
  if (!currentProcess.value.isEdit) {
    return jumpStep(process_name);
  }
  open.value = true;
};

const jumpStep = (process_name: ProcessType) => {
  let step = currentProcess.value.getStep(process_name);
  if (!step) {
    step = new JobStep(process_name, {});
    currentProcess.value.addNext(step);
  }
  currentProcess.value = step;
};
const onOk = async () => {
  if (jumpCallback.value) {
    await jumpCallback.value();
  }
  jumpStep(jumpProcess.value);
  open.value = false;
};
const onCancel = () => {
  jumpStep(jumpProcess.value);
  open.value = false;
};

const instanceRef = ref();
const changeStep = (val: number) => {
  const process_name = processCollections[val];
  const job = currentProcess.value.getStep(process_name);
  if (job) {
    if (currentProcess.value.isEdit) {
      instanceRef.value.change(process_name);
    } else {
      currentProcess.value = job;
    }
  }
};

const isFinish = ref(false);

useEventListener('beforeunload', e => {
  e.preventDefault();
  e.returnValue = '未保存的数据将会丢失，是否继续？';
});

const router = useRouter();
onMounted(() => {
  event.on('finish', () => {
    isFinish.value = true;
    router.push({
      path: `/category`,
    });
  });
});
onBeforeUnmount(() => {
  event.all.clear();
});
onBeforeRouteLeave((_to, _from, next) => {
  if (isFinish.value) {
    next();
  } else if (confirm('未保存的数据将会丢失，是否继续？')) {
    next();
  } else {
    next(false);
  }
});
</script>
